﻿/*
 guanaco.js unit testing
 Copyright (c) 2014 Walter M. Soto Reyes 
*/

(function () {

    //Unit test sample:
    //var unit = {
    //    test: function () { return true; },
    //    description: '',
    //    remarks: []
    //};
     
    var measure = (window.performance && window.performance.now);

    var clockIt = function () {
        if (measure) {
            return performance.now();
        }
        return 0;
    };

    var gua = {
        units: [],
        fails: 0,
        validUnit:function(u){
            if (typeof u.test === 'function' && typeof u.description !== 'undefined') {
                return true;
            }
            return false;
        },
        display:{
            parent: 'result',
            elementTag:'div'
        },
        classes:{
            pass: 'gua-pass',
            fail: 'gua-fail',
            item:'gua-item',
            remark: 'gua-remark',
            description: 'gua-desc'
        },
        time:0,
        begin:function(){
            if (typeof this.units !== 'undefined' && this.units.constructor === Array) {
                if (this.units.length > 0) {
                    var start = clockIt();
                    for (var i = 0, max = this.units.length; i < max ; i++) {
                        if (this.validUnit(this.units[i])) {
                            var result = this.units[i].test();
                            if (!result) {
                                this.fails++;
                            }
                            this.assert(result, this.units[i].description, this.units[i].remarks);
                        }   
                    }
                    var end = clockIt();
                    this.time = end - start;
                    this.footer();

                }
            }
        },
        assert: function (val, description, remark) {
           
            var p = document.getElementById(this.display.parent);
            if (typeof p !== 'undefined') {
                p.appendChild(this.item(val, description,remark));
            }
            
        },
        footer:function(){
            var p = document.getElementById(this.display.parent);
            if (typeof p !== 'undefined') {
                var l = document.createElement(this.display.elementTag);
                l.className = this.classes.item;
                var desc = (this.units.length - this.fails) + ' out of ' +
                    this.units.length + ' passed, ' +
                    this.fails + ' failures. ' + (measure?'execution time: '+this.time+' ms.':'');
                l.appendChild(document.createTextNode(desc));
                p.appendChild(l);
            }
        },
        item: function (pass,desc,remark) {
            var l = document.createElement(this.display.elementTag);
            l.className = pass ? this.classes.pass : this.classes.fail;
            l.className = l.className + ' ' + this.classes.item;
            l.appendChild(document.createTextNode(desc));
            if (typeof remark !== 'undefined' && remark.length > 0) {
                for (var r = 0, rm = remark.length; r < rm; r++) {
                    l.appendChild(this.remark(remark[r])); 
                }
                 
            }
            return l;
        },
        remark: function (txt) {
            var l = document.createElement(this.display.elementTag);
            l.className = this.classes.remark;
            l.appendChild(document.createTextNode(txt));
            return l;
        }

    };
    

    if (!window.guanaco) {
        window.guanaco = gua;
    }
   
})();